package cn.good.yan.service.t6;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * 6. CAS
 * CAS - 解决ABA问题
 * *
 *
 * @author shengren.yan
 * @create 2024-03-30
 */
public class CASDemo4 {
    public static void main(String[] args) {

        Book javaBook = new Book(1, "javaBook");
        Book mysqlBook = new Book(2, "mysqlBook");
        Book redisBook = new Book(3, "redisBook");
        Book javaBook2 = new Book(1, "javaBook");

        // 原子类 多个版本号参数
        AtomicStampedReference<Book> stampedReference = new AtomicStampedReference<>(javaBook, 1);
        // 获取当前值：stampedReference.getReference(）获取当前版本号：stampedReference.getStamp()
        System.out.println(stampedReference.getReference() + "\t" + stampedReference.getStamp());

        boolean b;
        // 将 javaBook 改为 mysqlBook、版本号stompedReference.getStump()（最新版本号），改为＋1操作 【操作成功】
        b = stampedReference.compareAndSet(javaBook, mysqlBook, stampedReference.getStamp(), stampedReference.getStamp() + 1);
        System.out.println(b + "\t" + stampedReference.getReference() + "\t" + stampedReference.getStamp());
        // 将 mysqlBook 改为 javaBook、版本号stompedReference.getStump()（最新版本号），改为＋1操作 【操作成功】
        b = stampedReference.compareAndSet(mysqlBook, javaBook, stampedReference.getStamp(), stampedReference.getStamp() + 1);
        System.out.println(b + "\t" + stampedReference.getReference() + "\t" + stampedReference.getStamp());
        // 将 mysqlBook 改为 redisBook、版本号stompedReference.getStump()（最新版本号），改为＋1操作 【操作失败】 原因：原子类最新的值：javaBook
        b = stampedReference.compareAndSet(mysqlBook, redisBook, stampedReference.getStamp(), stampedReference.getStamp() + 1);
        System.out.println(b + "\t" + stampedReference.getReference() + "\t" + stampedReference.getStamp());
        // 将 javaBook2 改为 javaBook、版本号stompedReference.getStump()（最新版本号），改为＋1操作 【操作失败】 原因：javaBook2和javaBook并不是同一个类
        b = stampedReference.compareAndSet(javaBook2, javaBook, stampedReference.getStamp(), stampedReference.getStamp() + 1);
        System.out.println(b + "\t" + stampedReference.getReference() + "\t" + stampedReference.getStamp());
        // 将 javaBook 改为 mysqlBook、版本号stompedReference.getStump()（最新版本号），改为＋1操作 【操作失败】 原因：版本号没有对应上
        b = stampedReference.compareAndSet(javaBook, mysqlBook,1, 2);
        System.out.println(b + "\t" + stampedReference.getReference() + "\t" + stampedReference.getStamp());
    }

}

// 实体
@NoArgsConstructor
@AllArgsConstructor
@Data
class Book {
    private int id;
    private String bookName;
}